﻿using System.Net.Http;
using System.Threading.Tasks;

namespace Sidvall.Net
{
	public sealed class SoapClient : ISoapClient
	{
		#region Public Members

		#region Dispose

		public void Dispose()
		{
			if (this._ClientProxy != null)
			{
				this._ClientProxy.Dispose();
				this._ClientProxy = null;
			}
			System.GC.SuppressFinalize(this);
		}

		#endregion
		#region SendSoapAsync

		public async Task<HttpResponse> SendSoapAsync(System.Uri requestUri, string soapAction, string content)
		{
			return await SendSoapAsync(requestUri, GetContent(content, soapAction)).ConfigureAwait(false);
		}
		private async Task<HttpResponse> SendSoapAsync(System.Uri requestUri, System.Net.Http.HttpContent content)
		{
			HttpResponseMessage responseMessage;

			responseMessage = await this.ClientProxy.PostAsync(requestUri, content).ConfigureAwait(false);

			return HttpManager.CreateResponseMessage(responseMessage);
		}

		#endregion

		#region ToString

		public override string ToString()
		{
			return "SoapClient - System.Net.Http.HttpClient (PCL)";
		}

		#endregion

		#endregion
		#region Private Members

		#region ClientProxy

		private System.Net.Http.HttpClient _ClientProxy;
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
		private System.Net.Http.HttpClient ClientProxy
		{
			get
			{
				HttpClientHandler handler;

				if (_ClientProxy == null)
				{
					handler = new HttpClientHandler();
					if (handler.SupportsAutomaticDecompression)
						handler.AutomaticDecompression = System.Net.DecompressionMethods.GZip | System.Net.DecompressionMethods.Deflate;
					_ClientProxy = new System.Net.Http.HttpClient(handler, true);
					if (!string.IsNullOrWhiteSpace(this.Settings.BaseAddress))
						_ClientProxy.BaseAddress = new System.Uri(this.Settings.BaseAddress);
				}
				return _ClientProxy;
			}
		}

		#endregion
		#region Settings

		private SoapClientSettings _Settings;
		private SoapClientSettings Settings
		{
			get
			{
				if (_Settings == null)
					_Settings = new SoapClientSettings();
				return _Settings;
			}
			set
			{
				_Settings = value;
			}
		}

		#endregion

		#region GetContent

		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")]
		private static System.Net.Http.HttpContent GetContent(string content, string soapAction)
		{
			System.Net.Http.HttpContent httpContent;
			string message;

			if (content == null)
				content = string.Empty;
			message = @"<s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/""><s:Body>" + content + @"</s:Body></s:Envelope>";
			httpContent = new StringContent(message, System.Text.Encoding.UTF8, "text/xml");
			if (!string.IsNullOrWhiteSpace(soapAction))
				httpContent.Headers.Add("SOAPAction", "\"" + soapAction + "\"");
			else
				httpContent.Headers.Add("SOAPAction", "\"\"");

			return httpContent;
		}

		#endregion

		#endregion
		#region Constructors

		public SoapClient()
		{
		}

		public SoapClient(SoapClientSettings settings)
		{
			this.Settings = settings;
		}

		#endregion
	}
}
